use std::{num::NonZeroU32, path::Path};

use image::*;

use crate::{function::render::rhi::Rhi, math::{ Vector2u}};

#[derive(Debug)]
pub struct Sampler {
    pub sampler: wgpu::Sampler,
    pub name: &'static str,
}

impl Sampler {
    pub fn new(rhi: Rhi, name: &'static str) -> Self {
        let sampler = rhi
            .borrow()
            .device
            .create_sampler(&wgpu::SamplerDescriptor {
                address_mode_u: wgpu::AddressMode::Repeat,
                address_mode_v: wgpu::AddressMode::Repeat,
                address_mode_w: wgpu::AddressMode::Repeat,
                mag_filter: wgpu::FilterMode::Linear,
                min_filter: wgpu::FilterMode::Nearest,
                mipmap_filter: wgpu::FilterMode::Nearest,
                ..Default::default()
            });
        Self { sampler, name }
    }
}

#[derive(Debug)]
pub struct Texture {
    pub texture: wgpu::Texture,
    pub view: wgpu::TextureView,
    pub path: &'static str,
    pub dimensions:Vector2u
}

impl Texture {
    pub fn from_path(rhi: Rhi, path: &'static str, label: Option<&'static str>) -> Self {
        let mut img: DynamicImage;

        img = image::open(&Path::new(path)).expect("load texture failed");
        img = img.flipv();
      
        Self::from_image(rhi, &img, path, label)
    }

    pub fn from_image(
        rhi: Rhi,
        img: &image::DynamicImage,
        path: &'static str,
        label: Option<&'static str>,
    ) -> Self {
        let rgba = img.to_rgba8();
        let dimensions = img.dimensions();

        let size = wgpu::Extent3d {
            width: dimensions.0,
            height: dimensions.1,
            depth_or_array_layers: 1,
        };
        let texture = rhi
            .borrow()
            .device
            .create_texture(&wgpu::TextureDescriptor {
                label,
                size,
                mip_level_count: 1,
                sample_count: 1,
                dimension: wgpu::TextureDimension::D2,
                format: wgpu::TextureFormat::Rgba8UnormSrgb,
                usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
            });

        rhi.borrow().queue.write_texture(
            wgpu::ImageCopyTexture {
                aspect: wgpu::TextureAspect::All,
                texture: &texture,
                mip_level: 0,
                origin: wgpu::Origin3d::ZERO,
            },
            &rgba,
            wgpu::ImageDataLayout {
                offset: 0,
                bytes_per_row: NonZeroU32::new(4 * dimensions.0),
                rows_per_image: NonZeroU32::new(dimensions.1),
            },
            size,
        );

        let view = texture.create_view(&wgpu::TextureViewDescriptor::default());

        Self {
            texture,
            view,
            path,
            dimensions:Vector2u::new(dimensions.0, dimensions.1)
        }
    }



}
